<?php
class Shop_Model_Cart extends Promotor_Model_Abstract {

	const NS = 'Shop_Model_Cart';
	const NS_UserData = 'UserData';

	/**
	 * @var Zend_Session_Namespace
	 */
	protected $_session;
	
	protected $_userData;

	/**
	 * @return void
	 */
	protected function __construct() {
		$this->_session = new Zend_Session_Namespace(self::NS, true);
		$this->_userData = new Zend_Session_Namespace(self::NS_UserData, true);
	}

	/**
	 * @var Shop_Model_Cart
	 */
	protected static $_instance;
	
	/**
	 * @return Shop_Model_Cart
	 */
	public static function getInstance() {
		if (null === self::$_instance) {
			self::$_instance = new self();
		}
		return self::$_instance;
	}

	/**
	 * @var Shop_Model_Product
	 */
	protected $_productModel;

	/**
	 * @return Shop_Model_Product
	 */
	public function getProductModel() {
		if (null === $this->_productModel) {
			$this->_productModel = new Shop_Model_Product();
		}
		return $this->_productModel;
	}

	/**
	 * @var array
	 */
	protected $_products = array();
	
	/**
	 * @param integer|string|Zend_Db_Table_Row_Abstract $identification
	 * @param string $key
	 * @param mixed $default
	 * @return mixed
	 */
	public function getProductData($identification, $key = null, $default = null) {
		if (!isset($this->_products[$identification])) {
			$this->_products[$identification] = array();
	
			if (is_numeric($identification)) {
				$this->_products[$identification] = $this->getProductModel()->findByIdAllInfoCache($identification);
			} elseif (is_string($identification)) {
				$this->_products[$identification] = $this->getProductModel()->findByIdAllInfoCache($identification);
			} elseif($identification instanceof Zend_Db_Table_Row_Abstract) {
				$this->_products[$identification] = $identification->toArray();
			}
		}

		return (null === $key)
			? $this->_products[$identification]
			: (array_key_exists($key, $this->_products[$identification])
				? $this->_products[$identification][$key] : $default);
	}

	protected function _prepareProductData($identification) {
		$data = $this->getProductData($identification);

		$promotion = (array_key_exists('promotion', $data)
			? $data['promotion'] : 0);
			
		$price = $promotion
			? Shop_Model_Promotion::price($data['price'], $data['modifer'], $data['value'])
			: $data['price'];
		
		return array(
			'id'       => $data['id'],
			'alias'    => $data['alias'],
			'name'     => $data['name'],

			'raw_price' => $data['price'],
		
			'price'    => $price,

			// czy promocja
			'promotion'=> $promotion,

			'image'    => @$data['image']['image'],
			'totalprice' => 0,
			'amount' => 0,

			'modifer' => $data['modifer'],
			'value'   => $data['value']
		);
	}
	
	/**
	 * @param integer|string|Zend_Db_Table_Row_Abstract $identification
	 * @return bool
	 */
	public function hasProduct($identification) {
		$id = $this->getProductData($identification, 'id');
		return isset($this->_session->$id);
	}
	
	/**
	 * @return integer
	 */
	public function hasProducts() {
		return count($this->_session->getIterator());
	}

	/**
	 * @param integer|string|Zend_Db_Table_Row_Abstract $identification
	 * @param integer $amount
	 * @return bool
	 */
	public function addProduct($identification, $amount = null) {
		$id = $this->getProductData($identification, 'id', false);

		if (false === $id) {
			$this->_setStatus(self::FAILURE);
			return false;
		}

		if (!isset($this->_session->$id)) {
			$this->_session->$id = $this->_prepareProductData($identification);
		}

		$p = $this->_session->$id;

		if (!is_numeric($amount)) {
			$p['amount']++;
		} else {
			$amount = (int) $amount;

			// ustaw liczbe produktów w koszyku
			if ($amount > 0) {
				$p['amount'] = $amount;
			} else
			// pomniejsz liczbe produktow w koszyku o 1
			if ($this->_session->$id['amount'] > 0) {
				$p['amount'];
			}
			// nie można pomnijszyć liczy produktów, więc nie rób nic!
			else {
				$this->_setStatus(self::FAILURE);
				return false;
			}
		}
		
		$p['totalprice'] = $p['amount'] * $p['price'];
		$this->_session->$id = $p;
		
		$this->_setStatus(self::SUCCESS);
		return true;
	}

	/**
	 * @param integer|string|Zend_Db_Table_Row_Abstract $identification
	 * @return bool
	 */
	public function removeProduct($identification) {
		$id = $this->getProductData($identification, 'id');
		if (isset($this->_session->$id)) {
			unset($this->_session->$id);
		}

		$this->_setStatus(self::SUCCESS);
	}

	/**
	 * @return array
	 */
	public function getProducts() {
		return $this->_session->getIterator()->getArrayCopy();
	}

	/**
	 * Ilość wszystkich produktów
	 * @return float
	 */
	public function getTotalQuantity() {
		$total = 0;
		foreach($this->_session as $product) {
			$total += $product['amount'];
		}
		return $total;
	}

	/**
	 * Kwota do zapłaty
	 * @return float
	 */
	public function getTotalPrice() {
		$total = 0;
		foreach($this->_session as $product) {
			$total += ($product['amount'] * $product['price']);
		}
		return number_format($total, 2);
	}
	
	public function setUserData(array $data)
	{
		$userDataKeys = array('fullname','email','phone','company','nip','address','amount','session_id','orderId',
							  'postcode','city','shipping_address','shipping_postcode','shipping_city');
		foreach ($data as $key => $val)
		{
			if (in_array($key, $userDataKeys))
			{
				$this->_userData->$key = $val;
			}
		}
	}
  
	/**
	 * @return array of values
	 * 
	 * 'fullname' => string
	 * 'email' => string
	 * 'phone' => string 
	 * 'company' => string
	 * 'nip' => string 
	 * 'address' => string 
	 * 'postcode' => string 
	 * 'city' => string
	 * 'shipping_address' => string 
	 * 'shipping_postcode' => string 
	 * 'shipping_city' => string 
	 * 'amount' => 
	 * 'orderId',
	 * 'session_id'
	 */
	public function getUserData()
	{
		return (array) $this->_userData->getIterator()->getArrayCopy();
	}
}